package com.baidu.mpks.role.service;

import com.baidu.mpks.permission.dao.PermissionDataRoleDao;
import com.baidu.mpks.permission.domain.Permission;
import com.baidu.mpks.permission.domain.PermissionDataRole;
import com.baidu.mpks.permission.dto.DataPermissionDto;
import com.baidu.mpks.permission.dto.TreePermissionDto;
import com.baidu.mpks.permission.dto.TypePermissionDto;
import com.baidu.mpks.permission.service.PermissionService;
import com.baidu.mpks.role.dao.RoleDao;
import com.baidu.mpks.role.domain.Role;
import com.baidu.mpks.role.dto.RoleDto;
import com.baidu.mpks.schema.dao.UserSchemaClassDao;
import com.baidu.mpks.schema.dao.UserSchemaPropertyDao;
import com.baidu.mpks.schema.domain.UserSchemaAll;
import com.baidu.mpks.schema.domain.UserSchemaClass;
import com.baidu.mpks.schema.domain.UserSchemaProperty;
import com.baidu.mpks.schema.service.UserSchemaPermissionService;
import com.baidu.mpks.tree.domain.UserTreeNode;
import com.baidu.mpks.tree.service.UserTreeService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RoleManageServiceImpl implements RoleManageService{

    @Autowired
    RoleDao roleDao;
    @Autowired
    RoleService roleService;
    @Autowired
    UserSchemaClassDao userSchemaClassDao;
    @Autowired
    UserSchemaPropertyDao userSchemaPropertyDao;
    @Autowired
    UserSchemaPermissionService userSchemaPermissionService;
    @Autowired
    UserTreeService userTreeService;
    @Autowired
    PermissionDataRoleDao permissionDataRoleDao;
    @Value("${permission.custom.nodeid.enabled}")
    private Boolean customNodeIdEnabled;
    @Value("${permission.custom.nodeid.list}")
    private String customNodeIdStr;
    private static final String CUSTOM_NODEID_SEPARATOR = ",";

    public RoleManageServiceImpl() {
    }

    public RoleDto findPermissionInfoByRoleId(int roleId) throws IllegalAccessException, InvocationTargetException {
        RoleDto roleDto = new RoleDto();
        Role role = this.roleDao.findById(roleId);
        BeanUtils.copyProperties(roleDto, role);
        roleDto.setPermissionList(this.roleDao.findPermissionListByRoleId(roleId));
        List<UserSchemaClass> allClass;
        if (roleId == 1) {
            allClass = this.userSchemaClassDao.getAll();
            List<UserTreeNode> allUserTreeNodes = this.userTreeService.getTreeNodes();
            Set<TreePermissionDto> treePermissionDtoList = new HashSet();
            Set<String> opList = new HashSet();
            PermissionService.OP[] var8 = PermissionService.OP.values();
            int var9 = var8.length;

            for(int var10 = 0; var10 < var9; ++var10) {
                PermissionService.OP op = var8[var10];
                opList.add(op.getName());
            }

            allUserTreeNodes.forEach((item) -> {
                TreePermissionDto temp = new TreePermissionDto();
                temp.setDataId(item.getId().toString());
                temp.setIdType(PermissionService.IDTYPE.SOURCE.getName());
                temp.setOp(opList);
                treePermissionDtoList.add(temp);
            });
            Set<TypePermissionDto> typePermissionDtoList = new HashSet();
            List<UserSchemaProperty> allProp = this.userSchemaPropertyDao.getAll();
            Map classToPropMap = (Map)allProp.stream().collect(Collectors.groupingBy(UserSchemaProperty::getDomain));

            try {
                List<UserSchemaAll> schemaAll = this.userSchemaPermissionService.getSchemaAll();
                Map<String, Set<String>> classAncestorMap = this.userSchemaPermissionService.getAncestorMap(schemaAll);
                allClass.forEach((item) -> {
                    TypePermissionDto temp = new TypePermissionDto();
                    temp.setClassId(item.getAtId());
                    temp.setIdType(PermissionService.IDTYPE.TYPE.getName());
                    temp.setOp(opList);
                    List<DataPermissionDto> propList = new ArrayList();
                    List<String> inheritPropList = item.getProperties();
                    Set<String> parentClass = new HashSet();
                    if (classAncestorMap.get(item.getAtId()) != null) {
                        parentClass.addAll((Collection)classAncestorMap.get(item.getAtId()));
                    }

                    List<UserSchemaProperty> parentPropList = new ArrayList();
                    parentClass.forEach((parentClassAtId) -> {
                        String domain = "[\"" + parentClassAtId + "\"]";
                        List<UserSchemaProperty> parentPropTempList = (List)classToPropMap.get(domain);
                        if (classToPropMap.get(domain) != null) {
                            parentPropList.addAll(parentPropTempList);
                        }

                    });
                    inheritPropList.addAll((Collection)parentPropList.stream().map(UserSchemaProperty::getAtId).collect(Collectors.toSet()));
                    inheritPropList.forEach((data) -> {
                        DataPermissionDto propData = new DataPermissionDto();
                        propData.setDataId(data);
                        propData.setOp(opList);
                        propList.add(propData);
                    });
                    temp.setPropIds(propList);
                    typePermissionDtoList.add(temp);
                });
            } catch (IOException var13) {
//                log.error("findPermissionInfoByRoleId getSchemaAll error ------> {}", var13.getMessage());
            }

            roleDto.setTreePermissionList(treePermissionDtoList);
            roleDto.setTypePermissionList(typePermissionDtoList);
        } else {
            RoleDto dto = this.findDataPermissionInfoByRoleId(roleId);
            roleDto.setTreePermissionList(dto.getTreePermissionList());
            roleDto.setTypePermissionList(dto.getTypePermissionList());
        }

        if (this.customNodeIdEnabled) {
            String[] nodeIdArr = StringUtils.split(this.customNodeIdStr, ",");
            Arrays.stream(nodeIdArr).forEach((nodeId) -> {
                TreePermissionDto treePermissionDto = new TreePermissionDto();
                treePermissionDto.setDataId(nodeId);
                treePermissionDto.setIdType(PermissionService.IDTYPE.SOURCE.getName());
                treePermissionDto.setOp(PermissionService.OP.getNames());
                roleDto.getTreePermissionList().remove(treePermissionDto);
                roleDto.getTreePermissionList().add(treePermissionDto);
            });
        }

        List<Permission>  allClassP = roleDto.getPermissionList();
        Iterator<Permission> iterator = allClassP.iterator();
        ArrayList auditPermissionList = new ArrayList();

        while(iterator.hasNext()) {
            Permission auditPermission = (Permission)iterator.next();
            if ("2".equals(auditPermission.getType())) {
                auditPermissionList.add(auditPermission);
                iterator.remove();
            }
        }

        roleDto.setAuditPermissionList(auditPermissionList);
        return roleDto;
    }

    private RoleDto findDataPermissionInfoByRoleId(int roleId) {
        RoleDto roleDto = new RoleDto();
        Set<PermissionDataRole> openPermissionList = this.permissionDataRoleDao.getOpenDataId();
        Map<String, Set<PermissionDataRole>> openPermissionMap = (Map)openPermissionList.stream().collect(Collectors.groupingBy(PermissionDataRole::getIdType, Collectors.toSet()));
        Set<PermissionDataRole> selfPermissionList = this.permissionDataRoleDao.getByRoleId(String.valueOf(roleId));
        Map<String, Set<PermissionDataRole>> selfPermissionMap = (Map)selfPermissionList.stream().collect(Collectors.groupingBy(PermissionDataRole::getIdType, Collectors.toSet()));
        Map<String, Set<String>> selfNodeOps = new HashMap();
        Map<String, Set<String>> openNodeOps = new HashMap();
        if (selfPermissionMap.get(PermissionService.IDTYPE.SOURCE.getName()) != null) {
            selfNodeOps = (Map)((Set)selfPermissionMap.get(PermissionService.IDTYPE.SOURCE.getName())).stream().collect(Collectors.groupingBy(PermissionDataRole::getDataId, Collectors.mapping(PermissionDataRole::getOp, Collectors.toSet())));
        }

        if (openPermissionMap.get(PermissionService.IDTYPE.SOURCE.getName()) != null) {
            openNodeOps = (Map)((Set)openPermissionMap.get(PermissionService.IDTYPE.SOURCE.getName())).stream().collect(Collectors.groupingBy(PermissionDataRole::getDataId, Collectors.mapping(PermissionDataRole::getOp, Collectors.toSet())));
        }

        Map<String, Set<String>> opMap = new HashMap();
        Set<String> allTreeDataIdList = new HashSet();
        allTreeDataIdList.addAll(((Map)selfNodeOps).keySet());
        allTreeDataIdList.addAll(((Map)openNodeOps).keySet());
        Iterator var11 = allTreeDataIdList.iterator();

        while(var11.hasNext()) {
            String dataId = (String)var11.next();
            Set<String> opSet = new HashSet();
            if (((Map)openNodeOps).get(dataId) != null) {
                opSet.addAll((Collection)((Map)openNodeOps).get(dataId));
            }

            if (((Map)selfNodeOps).get(dataId) != null) {
                opSet.addAll((Collection)((Map)selfNodeOps).get(dataId));
            }

            Set<String> nodesIncludeChildren = (Set)this.userTreeService.getChildrensNotIncludeSelf(Integer.parseInt(dataId)).stream().map(Object::toString).collect(Collectors.toSet());
            Iterator var15 = nodesIncludeChildren.iterator();

            while(var15.hasNext()) {
                String childNodeId = (String)var15.next();
                if (opMap.get(childNodeId) != null) {
                    ((Set)opMap.get(childNodeId)).addAll(opSet);
                } else {
                    Set<String> set = new HashSet();
                    set.addAll(opSet);
                    opMap.put(childNodeId, set);
                }
            }

            if (opMap.get(dataId) != null) {
                ((Set)opMap.get(dataId)).addAll(opSet);
            } else {
                Set<String> set = new HashSet();
                set.addAll(opSet);
                opMap.put(dataId, set);
            }
        }

        roleDto.setTreePermissionList((Set)opMap.entrySet().stream().map((i) -> {
            TreePermissionDto treePermissionDto = new TreePermissionDto();
            treePermissionDto.setDataId((String)i.getKey());
            treePermissionDto.setIdType(PermissionService.IDTYPE.SOURCE.getName());
            treePermissionDto.setOp((Set)i.getValue());
            return treePermissionDto;
        }).collect(Collectors.toSet()));
        Set<TypePermissionDto> typePermissionList = new HashSet();
        Set<PermissionDataRole> oriTypePermissionList = (Set)selfPermissionMap.get(PermissionService.IDTYPE.TYPE.getName());
        Map<String, TypePermissionDto> typeMap = this.roleService.addTypeOpTypeList(oriTypePermissionList);
        Map<String, TypePermissionDto> openTypeMap = this.roleService.addTypeOpTypeList((Set)openPermissionMap.get(PermissionService.IDTYPE.TYPE.getName()));
        Map<String, TypePermissionDto> allTypeMap = new HashMap();
        Set<String> allTypeDataIdList = new HashSet();
        allTypeDataIdList.addAll(openTypeMap.keySet());
        allTypeDataIdList.addAll(typeMap.keySet());

        String dataId;
        TypePermissionDto temp;
        for(Iterator var40 = allTypeDataIdList.iterator(); var40.hasNext(); allTypeMap.put(dataId, temp)) {
            dataId = (String)var40.next();
            temp = new TypePermissionDto();
            if (openTypeMap.get(dataId) != null && typeMap.get(dataId) != null) {
                try {
                    BeanUtils.copyProperties(temp, openTypeMap.get(dataId));
                } catch (InvocationTargetException | IllegalAccessException var32) {
//                    log.error(var32.getMessage());
                }

                Set<String> opList = ((TypePermissionDto)typeMap.get(dataId)).getOp();
                opList.addAll(((TypePermissionDto)openTypeMap.get(dataId)).getOp());
                temp.setOp(opList);
            } else if (openTypeMap.get(dataId) != null) {
                try {
                    BeanUtils.copyProperties(temp, openTypeMap.get(dataId));
                } catch (InvocationTargetException | IllegalAccessException var31) {
//                    log.error(var31.getMessage());
                }
            } else if (typeMap.get(dataId) != null) {
                try {
                    BeanUtils.copyProperties(temp, typeMap.get(dataId));
                } catch (InvocationTargetException | IllegalAccessException var30) {
//                    log.error(var30.getMessage());
                }
            }
        }

        Set<PermissionDataRole> oriPropPermissionList = (Set)selfPermissionMap.get(PermissionService.IDTYPE.FIELD.getName());
        Map<String, Set<String>> propOpMap = new HashMap();
        Map<String, List<DataPermissionDto>> propPermissionMap = new HashMap();
        Iterator var44;
        if (oriPropPermissionList != null) {
            var44 = oriPropPermissionList.iterator();

            while(var44.hasNext()) {
                PermissionDataRole item = (PermissionDataRole)var44.next();
                String classPropId = item.getDataId();
                String[] classPropIdArr = classPropId.split("@");
                String classId = classPropIdArr[0];
                String propId = classPropIdArr[1];
                TypePermissionDto classPermission = (TypePermissionDto)allTypeMap.get(classId);
                if (classPermission == null) {
                    classPermission = new TypePermissionDto();
                    classPermission.setClassId(classId);
                    classPermission.setOp(new HashSet());
                    classPermission.setIdType(PermissionService.IDTYPE.TYPE.getName());
                }

                DataPermissionDto propPermission = new DataPermissionDto();
                propPermission.setDataId(propId);
                Set<String> op = new HashSet();
                if (propOpMap.get(classPropId) != null) {
                    op = (Set)propOpMap.get(classPropId);
                }

                ((Set)op).add(item.getOp());
                propOpMap.put(classPropId, op);
                propPermission.setOp((Set)op);
                List<DataPermissionDto> propPermissionList = new ArrayList();
                if (classPermission.getPropIds() != null) {
                    propPermissionList = classPermission.getPropIds();
                }

                if (propPermissionMap.get(classPropId) == null) {
                    ((List)propPermissionList).add(propPermission);
                }

                propPermissionMap.put(classPropId, propPermissionList);
                classPermission.setPropIds((List)propPermissionList);
                allTypeMap.put(classId, classPermission);
            }
        }

        var44 = allTypeMap.values().iterator();

        while(var44.hasNext()) {
            TypePermissionDto item = (TypePermissionDto)var44.next();
            typePermissionList.add(item);
        }

        roleDto.setTypePermissionList(typePermissionList);
        return roleDto;
    }
}
